﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using l1cs.server.model;
using MySql.Data.MySqlClient;
using System.Data;
using l1cs.server.templates;
using l1cs.server.utils;
using l1cs.server.model.Instance;

namespace l1cs.server.datatables
{
    class NpcSpawnTable
    {
        private static Logger _log = Logger.getLogger( typeof( NpcSpawnTable ).FullName );

        private static NpcSpawnTable _instance;

        private Dictionary<int, L1Spawn> _spawntable = new Dictionary<int, L1Spawn>();

        private int _highestId;

        public static NpcSpawnTable getInstance()
        {
            if ( _instance == null )
            {
                _instance = new NpcSpawnTable();
            }
            return _instance;
        }

        private NpcSpawnTable()
        {/*TTOK*/
            int spawnCount = 0;
            String sqlstr = "SELECT * FROM spawnlist_npc";
            using ( MySqlWrapper wrapper = new MySqlWrapper() )
            {
                foreach ( DataRow item in wrapper.GetDataTable( sqlstr ).Rows )
                {
                    int npcid = SqlUtils.toInt( item["id"] );
                    if ( Config.ALT_GMSHOP == false )
                    {
                        if ( npcid >= Config.ALT_GMSHOP_MIN_ID && npcid <= Config.ALT_GMSHOP_MAX_ID )
                        {
                            continue;
                        }
                    }
                    if ( Config.ALT_HALLOWEENIVENT == false )
                    {
                        if ( npcid >= 130852 && npcid <= 130862 || npcid >= 26656 && npcid <= 26734 )
                        {
                            continue;
                        }
                    }
                    if ( Config.ALT_JPPRIVILEGED == false )
                    {
                        if ( npcid >= 1310368 && npcid <= 1310379 )
                        {
                            continue;
                        }
                    }
                    if ( Config.ALT_TALKINGSCROLLQUEST == false )
                    {
                        if ( npcid >= 87537 && npcid <= 87551 || npcid >= 1310387 && npcid <= 1310389 )
                        {
                            continue;
                        }
                    }
                    if ( Config.ALT_TALKINGSCROLLQUEST == true )
                    {
                        if ( npcid >= 90066 && npcid <= 90069 )
                        {
                            continue;
                        }
                    }
                    int npcTemplateid = SqlUtils.toInt( item["npc_templateid"] );
                    L1Npc l1npc = NpcTable.getInstance().getTemplate( npcTemplateid );
                    L1Spawn l1spawn;
                    if ( l1npc == null )
                    {
                        _log.warning( "mob data for id:" + npcTemplateid + " missing in npc table" );
                        l1spawn = null;
                    }
                    else
                    {
                        if ( SqlUtils.toInt( item["count"] ) == 0 )
                        {
                            continue;
                        }
                        l1spawn = new L1Spawn( l1npc );
                        l1spawn.setId( SqlUtils.toInt( item["id"] ) );
                        l1spawn.setAmount( SqlUtils.toInt( item["count"] ) );
                        l1spawn.setLocX( SqlUtils.toInt( item["locx"] ) );
                        l1spawn.setLocY( SqlUtils.toInt( item["locy"] ) );
                        l1spawn.setRandomx( SqlUtils.toInt( item["randomx"] ) );
                        l1spawn.setRandomy( SqlUtils.toInt( item["randomy"] ) );
                        l1spawn.setLocX1( 0 );
                        l1spawn.setLocY1( 0 );
                        l1spawn.setLocX2( 0 );
                        l1spawn.setLocY2( 0 );
                        l1spawn.setHeading( SqlUtils.toInt( item["heading"] ) );
                        l1spawn.setMinRespawnDelay( SqlUtils.toInt( item["respawn_delay"] ) );
                        l1spawn.setMapId( SqlUtils.toShort( item["mapid"] ) );
                        l1spawn.setMovementDistance( SqlUtils.toInt( item["movement_distance"] ) );
                        l1spawn.setName( l1npc.get_name() );
                        l1spawn.init();
                        spawnCount += l1spawn.getAmount();

                        _spawntable[l1spawn.getId()] = l1spawn;
                        if ( l1spawn.getId() > _highestId )
                        {
                            _highestId = l1spawn.getId();
                        }
                    }
                }
            }
            _log.config( "NPC配置リスト " + _spawntable.Count + "件ロード" );
            _log.fine( "総NPC数 " + spawnCount + "件" );
        }

        /// <summary>
        /// 出現するNPCをDBに追加する。
        /// </summary>
        /// <param name="pc"></param>
        /// <param name="npc"></param>
        public void storeSpawn( L1PcInstance pc, L1Npc npc )
        {
            int count = 1;
            String note = npc.get_name();
            String sqlstr = @"INSERT INTO spawnlist_npc SET 
                                location       = ?1,
                                count          = ?2,
                                npc_templateid = ?3,
                                locx           = ?4,
                                locy           = ?5,
                                heading        = ?6,
                                mapid          = ?7";
            MySqlCommand cmd = new MySqlCommand( sqlstr );
            using ( MySqlWrapper wrapper = new MySqlWrapper() )
            {
                cmd.Parameters.Add( "?", MySqlDbType.String ).Value = note;
                cmd.Parameters.Add( "?", MySqlDbType.Int32 ).Value = count;
                cmd.Parameters.Add( "?", MySqlDbType.Int32 ).Value = npc.get_npcId();
                cmd.Parameters.Add( "?", MySqlDbType.Int32 ).Value = pc.getX();
                cmd.Parameters.Add( "?", MySqlDbType.Int32 ).Value = pc.getY();
                cmd.Parameters.Add( "?", MySqlDbType.Int32 ).Value = pc.getHeading();
                cmd.Parameters.Add( "?", MySqlDbType.Int32 ).Value = pc.getMapId();
            }
        }

        /// <summary>
        /// 出現しているNPCを返す。
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        public L1Spawn getTemplate( int i )
        {
            L1Spawn ret;
            _spawntable.TryGetValue( i, out ret );
            return ret;
        }

        /// <summary>
        /// 出現するNPCを追加する。
        /// </summary>
        /// <param name="l1spawn"></param>
        public void addNewSpawn( L1Spawn l1spawn )
        {
            _highestId++;
            l1spawn.setId( _highestId );
            _spawntable[l1spawn.getId()] = l1spawn;
        }
    }
}
